#pragma once

namespace Graphics{
	class AnimationClip;
	typedef boost::shared_ptr<AnimationClip> AnimationClipPtr;

	struct AnimationFrame{
		std::vector<Utility::Math::Vector<float,3>> m_translate, 
													m_scale, 
													m_rotationAngle, 
													m_rotationAngleAnim;

		std::vector<Utility::Math::Matrix<4,4>> m_transforms;
		std::vector<Utility::Math::Matrix<4,4>> m_precomputedMatrices;
	};

	typedef boost::shared_ptr<AnimationFrame> AnimationFramePtr;

	class AnimationClip{
	public:
		AnimationClip(std::vector<unsigned int>& samplerIds, float startTime, float endTime, std::string &name);

		void computeClipJointFrame(float time, std::vector<Utility::Math::Matrix<4,4>>& joints, std::vector<Graphics::SkeletonJointPtr>& skelJoints, RenderContext* context);
		void computeClipJointFrame(float sourceTime, float targetTime, float interpolate, AnimationClipPtr targetClip, std::vector<Utility::Math::Matrix<4,4>>& joints, std::vector<Graphics::SkeletonJointPtr>& skelJoints, RenderContext* context);

		AnimationFramePtr getAnimationFrame(float time);

		std::string& getName() { return m_name; }
		float getStartMarker() { return m_start; }
		float getEndMarker() { return m_end; }
		std::vector<unsigned int>& getSamplerIds() { return m_samplerIds; }
	private:
		void composeMatrices(	std::vector<Utility::Math::Vector<float,3>>& translate,
								std::vector<Utility::Math::Vector<float,3>>& scale, 
								std::vector<Utility::Math::Vector<float,3>>& rotationAngle, 
								std::vector<Utility::Math::Vector<float,3>>& rotationAngleAnim,
								std::vector<Utility::Math::Matrix<4,4>>& transforms,
								std::vector<Graphics::SkeletonJointPtr>& skelJoints,
								std::vector<Utility::Math::Matrix<4,4>>& joints);
		void extractSamplerInformation(	float time,
										std::vector<unsigned int>& samplers, 
										std::vector<Utility::Math::Vector<float,3>>& translate, 
										std::vector<Utility::Math::Vector<float,3>>& scale, 
										std::vector<Utility::Math::Vector<float,3>>& rotationAngle, 
										std::vector<Utility::Math::Vector<float,3>>& rotationAngleAnim,
										std::vector<Utility::Math::Matrix<4,4>>& transforms,
										std::vector<Graphics::SkeletonJointPtr>& skelJoints, 
										RenderContext* context);

		std::string m_name;
		float m_start,m_end;
		std::vector<unsigned int> m_samplerIds;

		std::map<float,AnimationFramePtr> m_savedFrames;
	};
}